package com.tmt.im.manager.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.session.MapSession;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
import org.springframework.session.data.redis.RedisSessionMapper;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisIndexedHttpSession;

import java.util.Map;
import java.util.function.BiFunction;

/**
 * 使用以下配置修复RedisSessionMapper类中存在的BUG：
 * creationTime key must not be null
 *
 * @Description TODO
 * @Author wuyi
 * @Date 2024/9/29 9:33
 * @Version 1.0
 **/
@Configuration
@EnableRedisIndexedHttpSession
public class SessionConfig {

    @Bean
    public SessionRepositoryCustomizer<RedisIndexedSessionRepository> redisSessionRepositoryCustomizer() {
        return (redisSessionRepository) -> redisSessionRepository.setRedisSessionMapper(
                new SafeRedisSessionMapper(redisSessionRepository.getSessionRedisOperations()));
    }

    static class SafeRedisSessionMapper implements BiFunction<String, Map<String, Object>, MapSession> {

        private final RedisSessionMapper delegate = new RedisSessionMapper();

        private final RedisOperations<String, Object> redisOperations;

        SafeRedisSessionMapper(RedisOperations<String, Object> redisOperations) {
            this.redisOperations = redisOperations;
        }

        @Override
        public MapSession apply(String sessionId, Map<String, Object> map) {
            try {
                return this.delegate.apply(sessionId, map);
            } catch (IllegalStateException ex) {
                System.out.println("SafeRedisSessionMapper拦截到：" + ex.getMessage());
                // if you use a different redis namespace, change the key accordingly
                if (Boolean.TRUE.equals(this.redisOperations.delete("spring:session:sessions:" + sessionId))) { // we do not invoke RedisIndexedSessionRepository#deleteById to avoid an infinite loop because the method also invokes this mapper
                    System.out.println("删除Session：" + sessionId);
                }
                return null;
            }
        }

    }
}
